-module(pkt_ipv6_tests).

-include_lib("pkt/include/pkt.hrl").
-include_lib("eunit/include/eunit.hrl").

codec_test_() ->
    [
        decode(),
        encode(),
        ipv6_tcp_makesum_1(),
        ipv6_tcp_makesum_2(),
        ipv6_tcp_makesum_3(),
        ipv6_tcp_makesum_4(),
        ipv6_tcp_makesum_5(),
        ipv6_tcp_calculate_checksum_1(),
        ipv6_udp_makesum_1(),
        ipv6_udp_makesum_2(),
        ipv6_udp_makesum_3(),
        ipv6_udp_verify_checksum_1(),
        ipv6_udp_verify_checksum_2(),
        ipv6_udp_verify_checksum_3(),
        ipv6_tcp_verify_checksum_1(),
        ipv6_tcp_verify_checksum_2(),
        ipv6_tcp_verify_checksum_3(),
        ipv6_tcp_verify_checksum_4(),
        ipv6_tcp_verify_checksum_5(),
        ipv6_tcp_build_checksum_1(),
        ipv6_udp_build_checksum_1()
    ].

packet() ->
    <<96,0,0,0,0,64,58,64,32,1,4,112,0,8,16,109,20,26,254,106,
      31,249,166,149,38,7,248,176,64,11,8,10,0,0,0,0,0,0,16,3,
      128,0,255,149,7,79,0,1,169,244,102,82,0,0,0,0,36,187,0,
      0,0,0,0,0,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,
      31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,
      49,50,51,52,53,54,55>>.

decode() ->
    {Header, Payload} = pkt:ipv6(packet()),
    ?_assertEqual(
        {{ipv6,6,0,0,64,58,64,
         {8193,1136,8,4205,5146,65130,8185,42645},
         {9735,63664,16395,2058,0,0,0,4099}},
         <<128,0,255,149,7,79,0,1,169,244,102,82,0,0,0,0,36,187,0,
           0,0,0,0,0,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,
           31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,
           49,50,51,52,53,54,55>>},
        {Header, Payload}
    ).

encode() ->
    Packet = packet(),
    {Header, Payload} = pkt:ipv6(Packet),
    ?_assertEqual(Packet, <<(pkt:ipv6(Header))/binary, Payload/binary>>).

ipv6_tcp_packet_1() ->
      [#ipv6{v = 6,class = 0,flow = 0,len = 1432,next = 6,
       hop = 255,
       saddr = {8194,22395,62248,1,40647,42751,65133,30684},
       daddr = {8194,22395,62248,1,31176,62569,31957,35820}},
      #tcp{sport = 38197,dport = 50412,seqno = 3652146503,
           ackno = 3868632195,off = 5,cwr = 0,ece = 0,urg = 0,ack = 1,
           psh = 0,rst = 0,syn = 0,fin = 0,win = 1412,sum = 27913,
           urp = 0,opt = <<>>},
            <<78,55,71,187,185,209,73,255,
            142,147,190,182,92,23,117,230,123,216,1,29,226,13,191,126,171,117,21,51,235,222,45,238,67,214,254,26,239,
            28,118,83,156,119,248,252,3,124,87,27,126,4,121,6,218,187,9,214,253,26,215,32,132,173,167,134,167,
            128,7,148,17,125,32,211,221,8,124,122,139,154,46,49,250,147,229,91,96,14,54,132,157,161,22,187,46,185,
            60,13,198,168,70,234,51,42,169,79,169,164,166,79,13,106,47,151,240,178,181,57,34,221,145,80,
            23,164,217,207,247,251,64,182,219,89,119,130,108,193,54,214,84,199,9,126,7,125,190,45,93,
            219,213,250,193,223,92,184,211,190,39,168,129,46,218,18,54,0,111,58,204,97,198,74,166,242,
            125,171,154,88,150,138,189,170,2,160,39,149,97,184,238,183,98,28,215,199,12,90,211,147,165,
            13,149,173,104,79,40,53,16,83,219,54,159,36,91,240,110,15,223,219,223,94,0,125,184,183,179,
            238,35,61,179,158,169,156,151,165,251,30,239,60,22,51,82,125,255,80,176,103,243,71,100,79,
            221,71,68,90,15,249,32,62,181,33,150,77,13,50,101,231,32,139,108,57,21,83,119,246,78,237,
            160,223,253,72,167,153,70,5,191,111,209,182,206,116,248,92,198,196,9,65,95,27,170,92,207,
            226,216,86,150,174,85,8,226,94,59,32,226,227,93,197,164,175,213,185,47,190,249,83,49,103,
            142,194,255,255,51,242,236,49,192,63,226,30,241,142,253,128,125,96,225,135,159,165,52,109,
            173,242,121,51,189,159,161,124,129,115,0,158,213,197,249,7,230,191,32,158,221,173,233,235,
            178,109,13,20,15,181,112,16,27,250,74,185,140,131,251,19,53,169,46,170,189,81,44,105,47,239,
            151,53,227,42,232,171,57,56,127,72,120,158,163,21,253,182,188,188,31,249,183,172,93,254,168,
            121,207,42,199,226,149,44,120,31,212,121,57,183,187,173,200,130,78,139,204,51,152,37,48,198,
            31,53,231,21,243,188,8,158,203,156,243,40,237,109,253,162,61,23,224,189,96,251,190,61,158,19,
            141,89,246,59,34,68,91,244,168,75,46,1,249,96,140,116,238,57,194,146,31,172,167,238,2,157,221,
            175,16,137,203,94,249,40,123,9,155,11,191,44,110,103,104,127,225,151,39,46,99,157,97,131,219,
            35,254,224,121,5,113,197,247,234,195,23,146,82,45,251,40,204,171,179,152,6,242,142,41,95,241,
            59,108,16,118,250,187,195,219,62,99,17,174,121,114,57,43,104,217,194,21,237,118,221,69,123,241,
            81,207,92,136,115,109,43,212,77,187,122,63,211,222,129,242,14,63,202,231,112,107,254,134,113,17,
            140,7,8,187,239,183,58,31,167,232,163,202,130,103,204,243,250,172,177,100,58,206,231,250,31,165,
            119,37,39,19,75,22,194,51,20,192,123,152,38,19,201,130,95,252,199,71,105,237,111,137,180,28,230,
            107,132,141,107,126,214,92,92,119,146,48,136,35,42,213,41,208,56,215,129,6,112,95,177,236,49,187,
            79,172,189,215,61,141,237,124,207,113,8,244,182,250,234,70,138,233,18,159,19,246,27,55,238,83,80,
            6,138,194,152,226,242,40,238,203,111,62,169,179,116,159,20,221,248,44,137,193,120,139,45,200,123,
            129,143,223,149,172,133,37,182,105,56,102,164,116,173,129,103,57,64,134,20,112,113,127,17,199,123,
            195,154,71,209,110,143,94,123,156,219,44,101,125,255,119,132,241,241,131,253,253,137,24,71,189,
            127,215,74,235,147,173,20,207,63,216,103,146,10,136,94,19,107,73,37,242,194,122,61,211,27,107,216,
            163,109,144,158,239,193,15,119,25,108,120,239,126,148,229,244,26,214,210,106,201,105,60,223,103,
            35,207,242,116,168,211,66,30,128,97,202,72,97,110,67,164,62,166,179,122,22,1,190,83,64,60,58,202,
            115,143,217,252,17,219,230,233,39,130,247,164,166,112,121,134,211,47,208,31,202,94,214,56,118,159,
            189,175,187,69,103,214,249,251,211,125,48,15,229,166,144,83,61,221,147,44,59,33,120,22,159,159,201,
            135,49,177,167,54,130,182,152,228,211,108,62,47,99,97,183,2,227,210,144,139,63,123,204,179,175,104,
            239,45,234,97,222,239,232,123,234,232,151,67,32,91,118,224,29,59,249,254,91,196,253,26,227,175,128,
            46,65,191,208,162,143,115,185,118,79,173,130,253,16,116,124,238,5,216,114,18,6,125,67,200,167,191,
            79,132,164,129,190,238,86,251,126,169,209,44,23,131,142,90,119,11,234,183,205,76,219,78,65,223,49,
            200,111,74,114,178,73,223,146,2,253,146,169,53,36,60,79,180,7,126,23,238,158,30,176,224,23,47,121,
            28,244,13,37,184,112,247,110,24,195,209,73,102,93,89,103,235,231,36,212,89,109,253,38,142,246,88,
            128,55,64,221,7,160,237,253,128,31,60,123,142,245,168,91,132,231,74,30,55,199,233,60,41,77,75,25,
            175,207,230,199,105,26,244,81,193,179,74,200,253,183,2,159,222,100,64,63,148,73,188,207,32,95,114,
            209,23,101,110,103,28,242,97,125,240,94,17,222,241,69,89,95,123,74,224,4,243,131,30,126,133,61,110,
            16,54,180,153,239,137,0,60,28,55,88,207,58,128,175,189,252,56,69,93,252,94,115,142,248,222,34,29,
            250,167,76,194,181,129,5,121,221,68,219,205,24,224,94,254,224,181,112,155,184,39,111,60,161,86,124,
            14,244,148,114,102,245,55,142,173,205,183,146,96,166,86,101,11,239,9,75,153,25,89,233,193,195,165,
            210,247,110,209,165,226,19,143,123,238,217,159,78,118,0,111,46,225,231,131,22,112,251,75,184,142,
            151,13,142,133,43,235,140,254,135,64,107,238,249,229,67,160,45,180,133,97,157,215,119,63,23,189,
            109,218,160,156,69,74,249,57,46,243,12,23,158,231,130,241,94,202,199,228,49,98,174,245,8,27,171,
            200,15,140,25,36,138,247,164,190,241,54,149,32,93,148,175,135,117,185,206,118,221,100,152,107,142,
            138,117,86,75,230,118,9,239,48,108,222,99,241,64,173,59,238,240,227,42,43,95,220,209,99,38,1,121,
            188,81,172,67,61,218,0,190,110,157,249,171,133,122,105,13,34,125,210,188,19,60,102,93,63,30,249,
            18,212,173,20>>].

ipv6_tcp_makesum_1() ->
    Checksum = pkt:makesum(ipv6_tcp_packet_1()),
    ?_assertEqual(
        0,
        Checksum
    ).

ipv6_tcp_packet_2() ->
         [#ipv6{v = 6,class = 0,flow = 0,len = 20,next = 6,hop = 255,
                saddr = {8194,22395,62248,1,31176,62569,31957,35820},
                daddr = {8194,22395,62248,1,40647,42751,65133,30684}},
          #tcp{sport = 50412,dport = 38197,seqno = 3868632195,
                ackno = 3642886663,off = 5,cwr = 0,ece = 0,urg = 0,ack = 1,
                psh = 0,rst = 0,syn = 0,fin = 0,win = 53248,sum = 3865,
                urp = 0,opt = <<>>},
          <<>>].

ipv6_tcp_makesum_2() ->
    Checksum = pkt:makesum(ipv6_tcp_packet_2()),
    ?_assertEqual(
        0,
        Checksum
    ).

ipv6_tcp_packet_3() ->
        [#ipv6{v = 6,class = 0,flow = 0,len = 20,next = 6,hop = 255,
               saddr = {8194,22395,62248,1,31176,62569,31957,35820},
               daddr = {8194,22395,62248,1,40647,42751,65133,30684}},
         #tcp{sport = 50412,dport = 38197,seqno = 3868632195,
               ackno = 3645792503,off = 5,cwr = 0,ece = 0,urg = 0,ack = 1,
               psh = 0,rst = 0,syn = 0,fin = 0,win = 53248,sum = 47100,
               urp = 0,opt = <<>>},
         <<>>].

ipv6_tcp_makesum_3() ->
    Checksum = pkt:makesum(ipv6_tcp_packet_3()),
    ?_assertEqual(
        0,
        Checksum
    ).

ipv6_tcp_packet_4() ->
       [#ipv6{v = 6,class = 0,flow = 0,len = 57,next = 6,hop = 255,
              saddr = {8194,22395,62248,1,40647,42751,65133,30684},
              daddr = {8194,22395,62248,1,31176,62569,31957,35820}},
        #tcp{sport = 21,dport = 50411,seqno = 2610741794,
             ackno = 3765735301,off = 5,cwr = 0,ece = 0,urg = 0,ack = 1,
             psh = 1,rst = 0,syn = 0,fin = 0,win = 1412,sum = 40931,
             urp = 0,opt = <<>>},
        <<"220 FRITZ!Box3272 FTP server ready.\r\n">>].

ipv6_tcp_makesum_4() ->
    Checksum = pkt:makesum(ipv6_tcp_packet_4()),
    ?_assertEqual(
        0,
        Checksum
    ).

ipv6_tcp_packet_5() ->
       [#ipv6{v = 6,class = 0,flow = 0,len = 32,next = 6,hop = 255,
              saddr = {8194,22395,62248,1,40647,42751,65133,30684},
              daddr = {8194,22395,62248,1,31176,62569,31957,35820}},
        #tcp{sport = 21,dport = 50411,seqno = 2610741793,
              ackno = 3765735301,off = 8,cwr = 0,ece = 0,urg = 0,ack = 1,
              psh = 0,rst = 0,syn = 1,fin = 0,win = 5648,sum = 48664,
              urp = 0,
              opt = <<2,4,5,132,1,1,4,2,1,3,3,2>>},
        <<>>].

ipv6_tcp_makesum_5() ->
    Checksum = pkt:makesum(ipv6_tcp_packet_5()),
    ?_assertEqual(
        0,
        Checksum
    ).

ipv6_tcp_calculate_checksum_1() ->
    [IPv6, TCP, Payload] = ipv6_tcp_packet_5(),
    Checksum = pkt:makesum([IPv6, TCP#tcp{sum=0}, Payload]),
    ?_assertEqual(
        48664,
        Checksum
    ).

ipv6_udp_packet_1() ->
    [#ipv6{v = 6,class = 0,flow = 0,len = 42,next = 17,
       hop = 255,
       saddr = {8194,22395,51079,1,40407,23622,58249,17245},
       daddr = {64768,0,0,0,40647,42751,65133,30684}},
     #udp{sport = 9903,dport = 53,ulen = 42,sum = 55561},
     <<238,114,1,0,0,1,0,0,0,0,0,0,5,100,97,105,115,121,6,117,98,117,110,116,117,3,99,111,109,0,0,1,0,1>>].

ipv6_udp_packet_2() ->
    [#ipv6{v = 6,class = 0,flow = 0,len = 44,next = 17,hop = 1,
       saddr = {65152,0,0,0,21078,43263,65025,7903},
       daddr = {65282,0,0,0,0,0,1,2}},
     #udp{sport = 56868,dport = 547,ulen = 44,sum = 37991},
     <<11,53,24,20,0,8,0,2,255,255,0,1,0,14,0,1,0,1,26,213,31,121,80,86,168,1,30,223,0,6,0,4,0,23,0,31>>].

ipv6_udp_packet_3() ->
    [#ipv6{v = 6,class = 0,flow = 0,len = 287,next = 17,
       hop = 255,
       saddr = {64768,0,0,0,40647,42751,65133,30684},
       daddr = {8194,22395,51079,1,63891,16752,53406,9399}},
     #udp{sport = 53,dport = 53489,ulen = 287,sum = 34044},
     <<41,29,129,128,0,1,0,7,0,0,0,0,2,97,117,8,100,111,119,110,108,111,97,100,13,119,105,110,100,111,119,115,117,112,
     100,97,116,101,3,99,111,109,0,0,1,0,1,192,12,0,5,0,1,0,0,3,169,0,36,10,97,117,100,111,119,110,108,111,97,
     100,13,119,105,110,100,111,119,115,117,112,100,97,116,101,5,110,115,97,116,99,3,110,101,116,0,192,59,0,5,
     0,1,0,0,2,10,0,8,5,116,50,101,120,116,192,59,192,107,0,5,0,1,0,0,2,10,0,42,2,97,117,8,100,111,119,110,108,
     111,97,100,13,119,105,110,100,111,119,115,117,112,100,97,116,101,3,99,111,109,9,101,100,103,101,115,117,105,
     116,101,192,90,192,127,0,5,0,1,0,0,27,210,0,16,4,97,54,57,53,1,100,6,97,107,97,109,97,105,192,90,192,181,0,
     5,0,1,0,0,0,87,0,38,4,97,54,57,53,1,100,6,97,107,97,109,97,105,3,110,101,116,1,48,1,49,2,99,110,10,97,107,97,
     109,97,105,116,101,99,104,192,90,192,209,0,1,0,1,0,0,0,87,0,4,2,21,243,49,192,209,0,1,0,1,0,0,0,87,0,4,23,62,99,34>>].

ipv6_udp_makesum_1() ->
    Checksum = pkt:makesum(ipv6_udp_packet_1()),
    ?_assertEqual(
        16#FFFF,
        Checksum
    ).

ipv6_udp_makesum_2() ->
    Checksum = pkt:makesum(ipv6_udp_packet_2()),
    ?_assertEqual(
        16#FFFF,
        Checksum
    ).

ipv6_udp_makesum_3() ->
    Checksum = pkt:makesum(ipv6_udp_packet_3()),
    ?_assertEqual(
        16#FFFF,
        Checksum
    ).

ipv6_udp_verify_checksum_1() ->
    Result = pkt:verify_checksum(ipv6_udp_packet_1()),
    ?_assertEqual(
        true,
        Result
    ).

ipv6_udp_verify_checksum_2() ->
    Result = pkt:verify_checksum(ipv6_udp_packet_2()),
    ?_assertEqual(
        true,
        Result
    ).

ipv6_udp_verify_checksum_3() ->
    Result = pkt:verify_checksum(ipv6_udp_packet_3()),
    ?_assertEqual(
        true,
        Result
    ).

ipv6_tcp_verify_checksum_1() ->
    Result = pkt:verify_checksum(ipv6_tcp_packet_1()),
    ?_assertEqual(
        true,
        Result
    ).

ipv6_tcp_verify_checksum_2() ->
    Result = pkt:verify_checksum(ipv6_tcp_packet_2()),
    ?_assertEqual(
        true,
        Result
    ).

ipv6_tcp_verify_checksum_3() ->
    Result = pkt:verify_checksum(ipv6_tcp_packet_3()),
    ?_assertEqual(
        true,
        Result
    ).

ipv6_tcp_verify_checksum_4() ->
    Result = pkt:verify_checksum(ipv6_tcp_packet_4()),
    ?_assertEqual(
        true,
        Result
    ).

ipv6_tcp_verify_checksum_5() ->
    Result = pkt:verify_checksum(ipv6_tcp_packet_5()),
    ?_assertEqual(
        true,
        Result
    ).


ipv6_udp_build_checksum_1() ->
    Result = pkt:build_checksum(ipv6_udp_packet_1()),
    ?_assertEqual(
        {ipv6_udp, 55561},
        Result
    ).

ipv6_tcp_build_checksum_1() ->
    Result = pkt:build_checksum(ipv6_tcp_packet_1()),
    ?_assertEqual(
        {ipv6_tcp, 27913},
        Result
    ).
